package jfuzzyprincepless.zarchive.algorithm.structure.forcnstr;

import java.util.List;

import jfuzzyprincepless.agents.INegotiatingAgent;
import jfuzzyprincepless.zarchive.algorithm.structure.BaseNegotiationConstruction;
import jfuzzyprincepless.zarchive.algorithm.structure.ChainCommand;
import jfuzzyprincepless.zarchive.algorithm.structure.ICommandConstruction;
import jfuzzyprincepless.zarchive.negotiation.ZArchNegotiationUtils;
import laboratoryQ.computation.BaseUtils;

/**
 * BaseNegotiationForConstruction
 */
public abstract class BaseNegotiationFor<E>
	extends BaseNegotiationConstruction
	implements INegotiationFor<E>
{
	/**
	 * DESIGN NOTE:
	 * there is a copy-paste: IF and FOR negotiations both
	 * have set of commants and they both extract agents from
	 * theirs commands sets
	 * BUT
	 * IF has two kinds of commands list and it also has
	 * {@link jfuzzyprincepless.zarchive.algorithm.structure.ifcnstr.NegotiationIfConstruction#condition}
	 * moving functionality connected with commands and agents exctraction
	 * makes work with commansta, conditions ... more explicit
	 */
	protected ChainCommand forBodyCommands =
		new ChainCommand();

	protected BaseNegotiationFor(
		ICommandConstruction[] forBodyCommands,
		List<INegotiatingAgent> agents
	) {
		super(agents);
		BaseUtils.addAll(
			this.forBodyCommands.getCommandsList(),
			forBodyCommands
		);
	}

	@Override
	public List<ICommandConstruction> getCommandsList() {
		return forBodyCommands.getCommandsList();
	}

	/**
	 * DESIGN NOTE:
	 * here in many places inner field of type ArrayList<...>
	 * is returned without wrapping: Collections.unmodifiableList(...)
	 * because in multiagent systems it is frequently necessary to
	 * add/remove agents
	 * TOD O: change behavior to return Collections.unmodifiableList(...)
	 * when this approach becomes cause of problem
	 *
	 * OR
	 *
	 * TODOLONG: add something like method:
	 *	void freeze () {
	 *		agents = Collections.unmodifiableList(agents)
	 *	}
	 */

	@Override
	public void extractAgentsFromConstructions() {
		agents.clear();
		ZArchNegotiationUtils.addAgents(
			forBodyCommands.getCommandsList(),
			agents,
			ZArchNegotiationUtils.CMD_IS_AGENT
		);
	}

	public void addBodyCommands(ICommandConstruction ... commands) {
		BaseUtils.addAll(forBodyCommands.getCommandsList(), commands);
	}
}
